package com.activenetwork.smlite.page.event;

import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.activenetwork.smlite.page.generic.NexusProgressPageObjectListener;
import com.activenetwork.util.EnvContext;
import com.activenetwork.util.WaitUtil;


public class SmartFolder {
	private static Logger logger = LoggerFactory.getLogger(SmartFolder.class);
	private static By rootBy = By.cssSelector(".autotest-template-eventshomeview ul.jqtree-tree li.level0");
	private static By addFolderBtnBy = By.cssSelector("button#addHandler4Level1Folder");
	private static NexusProgressPageObjectListener nexusProgress = new NexusProgressPageObjectListener();
	private WebDriver driver = EnvContext.webDriverTL.get();
	private WaitUtil waitUtil = new WaitUtil();
	private FOLDER_LEVEL level;
	private String folderName;
	
	public SmartFolder(String folderName, FOLDER_LEVEL level){
		this.level = level;
		this.folderName = folderName;
	}
	
	/**
	 * Create a smart folder and return the instance to represent it
	 * @param level1FolderName
	 * @return
	 */
	public static SmartFolder createLevel1Folder(String level1FolderName){
		WebDriver driver = EnvContext.webDriverTL.get();
		WebElement addFolderBtn = driver.findElement(addFolderBtnBy);
		addFolderBtn.click();
		nexusProgress.waitProgress("SmartFolderBar");
		WebElement li = driver.findElement(rootBy).findElement(By.xpath(".//li[contains(@class, 'level1')][last()]"));
		WebElement liText = li.findElement(By.xpath(".//input[@type='text']"));
		liText.clear();
		liText.sendKeys(level1FolderName, Keys.ENTER);
		nexusProgress.waitProgress("SmartFolderBar");
		logger.debug("Create level 1 folder " + level1FolderName);
		return new SmartFolder(level1FolderName, FOLDER_LEVEL.LEVEL1);
	}
	
	/**
	 * Find the web element of the specific smart folder by name
	 * @return
	 */
	public WebElement getFolderElement(){
		// expand all the cascading folders
		expandAll(FOLDER_LEVEL.LEVEL1);	
		expandAll(FOLDER_LEVEL.LEVEL2);
		List<WebElement> lis = driver.findElement(rootBy).findElements(By.xpath(".//li[contains(@class, '" + level.getLevel() + "')]"));
		for(WebElement li : lis){
			String name = li.findElement(By.xpath("./div/span[@class='jqtree-title']")).getText().trim();
			if(folderName.equals(name)){
				return li;
			}
		}
		throw new RuntimeException("Not found " + level.getLevel() + " folder " + folderName);
	}
	
	private void expandAll(FOLDER_LEVEL level){	
		if(level == FOLDER_LEVEL.LEVEL3) throw new RuntimeException("Level 3 is the deepest folder that can not expand");
		By levClosedBy = By.xpath(".//li[contains(@class, '" + level.getLevel() + "') and contains(@class, 'jqtree-closed')]");
		int lev_closed = driver.findElement(rootBy).findElements(levClosedBy).size();
		for(int i=0;i<lev_closed;i++){
			WebElement li = driver.findElement(rootBy).findElements(levClosedBy).get(0);
			li.findElement(By.xpath("./div/a")).click();
			waitUtil.wait(500);
		}
	}
	
	/**
	 * Click the edit icon of the specific smart folder
	 * @param li
	 */
	private void clickEdit(WebElement li){
		li.findElement(By.xpath("./div/span[contains(@class,'jqtree-action')]/i")).click();
		waitUtil.wait(250);
	}
	/**
	 * Create sub folder of specific smart folder	
	 * @param folderName
	 * @return
	 */
	public SmartFolder newSubfolder(String folderName){
		WebElement li = getFolderElement();
		clickEdit(li);
		try{
			driver.findElement(By.cssSelector("li.jqtree-menu[data-tree-action='add'] a")).click();
			waitUtil.wait(250);
			WebElement newSubText = getFolderElement().findElement(By.xpath("./ul/li[last()]//input[@type='text']"));
			newSubText.clear();
			newSubText.sendKeys(folderName, Keys.ENTER);
			nexusProgress.waitProgress("SmartFolderBar");
			logger.debug("New sub " + level.getLevel() + " smart folder " + folderName);
			return new SmartFolder(folderName, level.getNextLevel());
		}catch(NoSuchElementException e){
			throw new RuntimeException("Unable to create sub folder for " + level.getLevel() + " folder " + folderName);
		}
	}
	/**
	 * Rename the specific smart folder
	 * @param folderName
	 * @return
	 */
	public SmartFolder rename(String folderName){
		WebElement li = getFolderElement();
		clickEdit(li);
		try{
			driver.findElement(By.cssSelector("li.jqtree-menu[data-tree-action='rename'] a")).click();
			waitUtil.wait(250);
			WebElement text = li.findElement(By.xpath(".//input[@type='text']"));
			text.clear();
			text.sendKeys(folderName, Keys.ENTER);
			nexusProgress.waitProgress("SmartFolderBar");
			logger.debug("Rename " + level.getLevel() + " smart folder " + this.folderName + " to " + folderName);
			return new SmartFolder(folderName, level.getCurrentLevel());
		}catch(NoSuchElementException e){
			throw new RuntimeException("Unable to rename the " + level.getLevel() + " folder " + folderName);
		}
		
	}
	/**
	 * Delete the specified smart folder
	 */
	public void delete(){
		WebElement li = getFolderElement();
		clickEdit(li);
		try{
			driver.findElement(By.cssSelector("li.jqtree-menu[data-tree-action='remove'] a")).click();
			nexusProgress.waitProgress("SmartFolderBar");
			logger.debug("Delete " + level.getLevel() + " smart folder " + folderName);
		}catch(NoSuchElementException e){
			throw new RuntimeException("Unable to delete the " + level.getLevel() + " folder " + folderName);
		}
		
	}
	/**
	 * Highlight the specific smart folder
	 */
	public void highlight(){
		WebElement li = getFolderElement();
		li.findElement(By.xpath(".//span[@class='jqtree-title']")).click();
		nexusProgress.waitProgress("SmartFolderBar");
	}
	
	public enum FOLDER_LEVEL{
		LEVEL1("level1"),
		LEVEL2("level2"),
		LEVEL3("level3");
		
		final String level;
		
		FOLDER_LEVEL(String level){
			this.level = level;
		}	
		public String getLevel(){
			return this.level;
		}
		public FOLDER_LEVEL getNextLevel(){
			if(this.level.equals(LEVEL1.getLevel())){
				return FOLDER_LEVEL.LEVEL2;
			}else if(this.level.equals(LEVEL2.getLevel())){
				return FOLDER_LEVEL.LEVEL3;
			}else{
				throw new RuntimeException("Unable to get next level for level 3");
			}
		}
		public FOLDER_LEVEL getCurrentLevel(){
			if(this.level.equals(LEVEL1.getLevel())){
				return FOLDER_LEVEL.LEVEL1;
			}else if(this.level.equals(LEVEL2.getLevel())){
				return FOLDER_LEVEL.LEVEL2;
			}else{
				return FOLDER_LEVEL.LEVEL3;
			}
		}
	}

}
